/******************************************************************************
* 	Copyright (c) 2007-2008 All rights reserved
*		Asemantics S.r.l
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer. 
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by 
*	 Asemantics S.r.l."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. All advertising materials mentioning features or use of this software
*    must display the following acknowledgement:
*    This product includes software developed by Asemantics S.r.l.
*    the Semantic Web company, Rome, London, Leiden and its contributors. 
*
* 5. Neither the name of the company nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Andrea Marchesini - baku@asemantics.com
*
******************************************************************************/

#ifndef _TB_CONTROLLER_H_
#define _TB_CONTROLLER_H_

#include <glib.h>
#include <glib/gstdio.h>

#include <thebox/tb_keyvalue.h>

#define TB_SWAP_DEFAULT			1024 * 1024
#define TB_SWAP_FILE_DEFAULT		1024 * 1024 * 1024
#define TB_NETWORK_TIMEOUT_DEFAULT	5
#define TB_NETWORK_LISTEN_DEFAULT	5
#define TB_WAIT_MAX_ISTANCE		100

#define TB_ISTANCE_SPLITTER	"__TB_CONTROLLER_SPLITTER_IDENTIFIER__"

typedef enum {
  LOG_VERBOSE_ERROR,
  LOG_VERBOSE_WARNING,
  LOG_VERBOSE_INFO,
  LOG_VERBOSE_DEBUG
} LogVerbose;

typedef struct tb_env_t TBEnv;
struct tb_env_t
{
  gchar *	env;
  gchar *	value;
};

typedef enum
{
  TB_OPERATION_NONE = 0,
  TB_OPERATION_LIST,
  TB_OPERATION_PROCESS
} TBOperation;

typedef struct tb_swap_t TBSwap;
struct tb_swap_t
{
  gchar *	directory;

  guint64	size;
  guint64	filesize;

  gint		id;

  GMutex *	mutex;
};

typedef struct tb_swapfile_t TBSwapFile;
struct tb_swapfile_t
{
  gchar *	file;

  GIOChannel *	io;
  guint64	size;
  guint64	offset;
};

typedef struct tb_io_string_t TBIOString;
struct tb_io_string_t
{
  gboolean	is_rw;

  union
  {
    struct
    {
      GString *		string;

      TBSwap *		swap;
      GList *		swapfiles;
    } rw;

    struct
    {
      TBIOString *	string;
      guint64		offset;
    } ro;
  };

  guint64	size;
  guint		ref;
};

typedef struct tb_global_t TBGlobal;
struct tb_global_t
{
  gchar *	configfile;		/* Config File */

  GMutex *	logmutex;		/* Mutex about the log */
  GIOChannel *	logio;			/* Log IO Channel */
  gchar *	logfile;		/* Log File */
  LogVerbose	logverbose;

  TBSwap	swap;			/* Swap stuff */

  gboolean	background;		/* Demonize or not */
  gchar *	pidfile;		/* Pid File */

  gchar *	user;			/* Permissions */
  gchar *	group;

  GMutex *	mutex;			/* Mutex for these lists: */

  GList *	processes;		/* List of processes */
  GList *	istances;		/* List of istances */
  GList *	istances_wait;		/* List of istance waiting */
  guint		istances_wait_numb;
  guint		wait_max_istance;	/* Max number of istance waiting */

  GList *	envs;			/* List of envs */

  GMainLoop *	loop;
  GSource *	loop_source;

  TBOperation	operation;

  /* Info about the socket: */
  GThread *	net_thread;
  GMainContext * net_context;
  GMainLoop *	net_loop;

  gboolean	net_active;
  gchar *	net_interface;
  gint		net_port;
  gint		net_listen;
  gint		net_maxclients;
  gint		net_timeout;
  gboolean	net_ipv6;

  GIOChannel *	net_socket;
  GSource *	net_socket_source;

  GList *	net_clients;
  guint		net_clients_numb;
};

/* A TBProcess is the description of a process. */
typedef struct tb_sub_process_t TBSubProcess;
struct tb_sub_process_t
{
  gchar *	process;		/* Sub process */
  guint		order;
};

typedef struct tb_process_t TBProcess;
struct tb_process_t
{
  gchar *	id;			/* The name of this process */
  gboolean	multiple;		/* Multiple or not ? default: false */
  gboolean	hidden;			/* This process doesn't appear in the list
  					   requests */
  gboolean	global;			/* Does it have a parent ? */
  gboolean	meta;			/* Is it a meta process ? */
  
  guint		istances;		/* How many istances for this process ? */
  guint		istances_running;	/* How many istances are running now ? */

  guint		istances_wait_numb;	/* Number of istance waiting about this
  					   process */

  gchar *	command;		/* Command */
  gboolean	command_inline;		/* Inline? */

  TBIOString *	input;			/* Input */
  gboolean	input_trim;		/* Is it to trim? */
  gboolean	input_from_parent;	/* Input from parent */

  guint		scheduled;		/* If it is scheduled...  */
  GTime		last_scheduled;
  gboolean	wait_for_istances;

  GList *	processes;		/* SubProcess */

  guint		ref;			/* Counter of references */
  gboolean	is_ref;

  gboolean	is_to_schedule;		/* HTTP request... */
};

typedef struct tb_istance_t TBIstance;
struct tb_istance_t
{
  TBGlobal *		data;		/* Pointer to the global data */
  TBProcess *		process;	/* Pointer to the process */
  guint			process_order;	/* Order of this process */

  GList *		parents;	/* List of istances parent */

  GList *		metaprocesses;	/* Metaprocess for this istance */

  GTime			time;		/* Timestamp */
  GPid			pid;		/* Pid of the process */

  TBIOString *		input;		/* Info about input */
  guint64		input_written;

  TBIOString *		output;		/* String for output message */
  TBIOString *		error;		/* String for error message */

  GIOChannel *		io_input;	/* The input stream */
  guint			io_input_source;

  GIOChannel *		io_output;	/* The output stream */
  guint			io_output_source;

  GIOChannel *		io_error;	/* The error stream */
  guint			io_error_source;

  guint		ref;			/* Counter of references */
};

typedef struct tb_istance_wait_t TBIstanceWait;
struct tb_istance_wait_t
{
  TBProcess *		process;
  guint			process_order;	/* Order of this process */

  GList *		parents;

  TBIOString *		input;

  GList *		metaprocesses;
};

typedef struct tb_network_client_t TBNetworkClient;
struct tb_network_client_t
{
  TBGlobal *	data;

  gchar *	ip;

  GIOChannel *	channel;
  GSource *	timeout_source;
  GSource *	channel_source;

  gchar *	header;

  gchar *	output;
  gsize		output_size;
  gsize		output_done;
};

GQuark		controller_error_quark	(void);

#ifdef TB_DEBUG
typedef struct tb_debug_t TBDebug;
struct tb_debug_t
{
  gchar *	message;
  time_t	time;
  guint		repeat;
};

extern GStaticMutex	debug_mutex;
extern GList *		debug_strings;

void	debug				(const gchar *	func, 
					 const gint	line,
					 gchar *	format,
					 ...);
#endif

#endif

/* EOF */
